package com.quanquan.user.service;

import DTO.PageDTO;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.quanquan.user.dto.ConsumptionQuotaDTO;
import com.quanquan.user.entity.ConsumptionQuota;
import com.quanquan.user.exception.ConsumptionQuotaException;
import com.quanquan.user.repository.ConsumptionQuotaRepository;
import com.quanquan.user.request.ConsumptionQuotaRequestBody;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.core.internal.Function;
import org.springframework.data.domain.*;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import utils.DateUtils;
import utils.UUIDGenerator;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 功能描述:
 *
 * @ClassName: ConsumptionQuotaService
 * @Author: xiaoqianh丶
 * @Date: 2019-06-06 10:40
 * @Version: V1.0
 */
@Service
public class ConsumptionQuotaService {

    private static final String CONSUMPTION_QUOTA_RULE = "consumptionQuotaRule";
    private final ConsumptionQuotaRepository consumptionQuotaRepository;

    private final StringRedisTemplate redisTemplate;

    public ConsumptionQuotaService(ConsumptionQuotaRepository consumptionQuotaRepository, StringRedisTemplate redisTemplate) {
        this.consumptionQuotaRepository = consumptionQuotaRepository;
        this.redisTemplate = redisTemplate;
    }


    /**
     * 创建满额规则
     *
     * @param requestBody
     * @return
     */
    public String createConsumption(ConsumptionQuotaRequestBody requestBody) {
        ConsumptionQuota consumptionQuota = new ConsumptionQuota();
        //通过映射关系来赋值 //TODO 断点看一下
        BeanUtils.copyProperties(requestBody, consumptionQuota);
        consumptionQuota.setId(UUIDGenerator.getUUID());
        consumptionQuota.setCreateTime(DateUtils.currentDate());
        consumptionQuota.setRemove(0);
        consumptionQuotaRepository.save(consumptionQuota);
        //替换满额规则
        calculation();
        return "创建成功";
    }

    /**
     * 满额规则列表
     *
     * @param requestBody
     * @return
     */
    public PageDTO<ConsumptionQuotaDTO> findAllConsumption(ConsumptionQuotaRequestBody requestBody) {
        List<ConsumptionQuota> list = new ArrayList<>();
        Integer page = requestBody.getPage();
        Integer size = requestBody.getSize();
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(page, size, sort);
        ConsumptionQuota consumptionQuota = new ConsumptionQuota();
        consumptionQuota.setRemove(0);
        Example<ConsumptionQuota> example = Example.of(consumptionQuota);
        Page<ConsumptionQuota> findAll = consumptionQuotaRepository.findAll(example, pageable);
        list = findAll.getContent();
        List<ConsumptionQuotaDTO> consumptionQuotaDTOS = new ArrayList<>();
        for (ConsumptionQuota consumptionQuota1 : list) {
            ConsumptionQuotaDTO consumptionQuotaDTO = new ConsumptionQuotaDTO();
            //通过映射关系来赋值 //TODO 断点看一下
            BeanUtils.copyProperties(consumptionQuota1, consumptionQuotaDTO);
            consumptionQuotaDTO.setConsumptionId(consumptionQuota1.getId());
            consumptionQuotaDTOS.add(consumptionQuotaDTO);
        }


        PageDTO<ConsumptionQuotaDTO> pageDTO = new PageDTO<>();
        pageDTO.setTotal(findAll.getTotalElements());
        pageDTO.setList(consumptionQuotaDTOS);
        pageDTO.setTotalPage(findAll.getTotalPages());
        pageDTO.setPage(page);
        pageDTO.setPageSize(size);

        return pageDTO;
    }


    /**
     * 根据阀值查询满额规则
     *
     * @param threshoid
     * @return
     */
    public ConsumptionQuota findConsumptionQuota(String threshoid) throws ConsumptionQuotaException {
        List<ConsumptionQuota> consumptionQuotas = consumptionQuotaRepository.findByThreshoidAndRemove(threshoid, 0);
        if (consumptionQuotas.size() <= 0) {
            throw new ConsumptionQuotaException("规则已失效");
        }
        return consumptionQuotas.get(0);

    }


    /**
     * 每次添加新的数据就进行范围变动计算并且将范围缓存到redis
     */
    public void calculation() {
        //先将所有范围查到
        //取出对象的阀值（根据阀值去重）生成字符串
        //缓存到redis
        List<ConsumptionQuota> consumptionQuotas = consumptionQuotaRepository.findAllByRemoveOrderByThreshoidDesc(0);
        List<String> threshoid = consumptionQuotas.parallelStream().filter(distinctByKey(ConsumptionQuota::getThreshoid)).map(ConsumptionQuota::getThreshoid).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        LinkedList<Integer> objects = new LinkedList<>();
        LinkedList<String> objects2 = new LinkedList<>();
        for (String threshold:threshoid) {
            Integer integer = Integer.valueOf(threshold);
            objects.add(integer);
        }
        objects.sort(Comparator.reverseOrder());
        System.out.println("threshoid........"+objects);
        for (Integer integer:objects) {
            String s = String.valueOf(integer);
            objects2.add(s);

        }
        //将阀值变成字符串
        String consumptionQuotaRule = String.join(",", objects2);
        //将字符串存到缓存
        redisTemplate.opsForValue().set(CONSUMPTION_QUOTA_RULE, consumptionQuotaRule);

    }

    private static <T> java.util.function.Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    public String updateConsumptionQuota(ConsumptionQuotaRequestBody requestBody) throws ConsumptionQuotaException {
        String consumptionId = requestBody.getConsumptionId();
        ConsumptionQuota consumptionQuota = consumptionQuotaRepository.findByIdAndRemove(consumptionId, 0);
        if (consumptionQuota == null) {
            throw new ConsumptionQuotaException("规则已失效");
        }
        BeanUtil.copyProperties(requestBody, consumptionQuota,true, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        consumptionQuotaRepository.save(consumptionQuota);
        //替换满额规则
        calculation();
        return "修改成功";
    }


    public String removeConsumptionQuota(ConsumptionQuotaRequestBody requestBody) throws ConsumptionQuotaException {
        String consumptionId = requestBody.getConsumptionId();
        ConsumptionQuota consumptionQuota = consumptionQuotaRepository.findByIdAndRemove(consumptionId, 0);
        if (consumptionQuota == null) {
            throw new ConsumptionQuotaException("规则已失效");
        }
        consumptionQuota.setRemove(1);
        consumptionQuotaRepository.save(consumptionQuota);
        return "删除成功";
    }

    /**
     * 查询满额规则详情
     * @param requestBody
     * @return
     */
    public ConsumptionQuotaDTO query(ConsumptionQuotaRequestBody requestBody) throws ConsumptionQuotaException {
        String consumptionId = requestBody.getConsumptionId();
        ConsumptionQuota consumptionQuota = consumptionQuotaRepository.findByIdAndRemove(consumptionId, 0);
        if (consumptionQuota == null) {
            throw new ConsumptionQuotaException("规则已失效");
        }
        ConsumptionQuotaDTO consumptionQuotaDTO = new ConsumptionQuotaDTO();
        BeanUtils.copyProperties(consumptionQuota, consumptionQuotaDTO);
        consumptionQuotaDTO.setConsumptionId(consumptionQuota.getId());
        return consumptionQuotaDTO;
    }
}

